這裡是「Three.js學習日誌」的第3篇,本篇的主旨是透過試做一個Three.js的Hello World案例,來讓讀者對於Three.js有基本的認識,這系列的文章假設讀者看得懂javascript,並且有Canvas 2D Context的相關知識。
第一次使用three.js
,尤其是那些沒有使用過3D建模軟體的人,多半會對每一個基本操作都有不小的疑問,畢竟three.js
提供的API種類繁多,而且光看官方文件又有一大堆的專有名詞,讓人頭昏眼花。
建議初學者可以先去玩過隨便一款3D建模軟體(首推Blender),畢竟菜鳥如小弟我就是這麼做的。
這邊我們會先做一個簡單的Hello World,並且一步一步講解每個步驟的用意,目的是希望可以讓讀者試試味道,並且對Three.js產生基本的認識。
這個Hello World的目標是要畫出來一個轉動的立方體(如圖)。
為了求快速,在這個案例中我們先用codepen
搭配https://cdn.skypack.dev
提供的CDN來取得three.js
的module。
import {
... //這邊接著會引入必要的模組
} from "https://cdn.skypack.dev/three";
Scene這個類別按字面解釋就是景,他有點像是世界的概念,當我們要去把一個three.js
的程序render出畫面,基本上就是要去渲染這個景裡面所有物件構成的圖像。
import {
Scene
} from "https://cdn.skypack.dev/three";
function main (){
const scene = new Scene();
}
main();
three.js
其實有提供很多種類的renderer
,但是最常用的基本上還是WebGLRenderer
。渲染器顧名思義當然是用來渲染用的,他本身會提供一個render
方法,可以用來把一個Scene
中的圖像渲染出來。
這邊我們順手設置antialias
(反鋸齒)和alpha
(開啟透明通道)兩個option。
antialias
(反鋸齒)是一種特殊的演算法,他可以用來柔化圖形邊緣因為像素顆粒太明顯而形成的鋸齒狀瑕疵。
而之所以要開啟alpha
(透明通道)是因為three.js
預設是不渲染透明通道的(也就是背景會全黑)。
還記得我們在前面演示過webgl清除畫布的方法嗎? 就是藉由填入特定的clearColor來達到清除的效果,清除色是可以設定為具有透明度的顏色的,所以假如我們要讓canvas
背景為透明無色,那就必須要:
設置完
renderer
實例之後要記得把renderer.domElement
放到dom tree裡面(domElement其實就是canvas)
import {
Scene
WebGLRenderer
} from "https://cdn.skypack.dev/three";
function main (){
const scene = new Scene();
const renderer = new WebGLRenderer({
antialias: true,
alpha: true
});
document.body.append(renderer.domElement);
}
main();
這邊應該就沒甚麼特別的,Viewport
其實就是我們在上一篇介紹過的gl.viewport
方法,也就是畫布範圍的映射。
畫布大小與Viewport,還有清除色的設定方法都可以從renderer
物件底下取得,他們分別是renderer.setSize
,renderer.setViewport
,還有renderer.setClearColor
。
import {
Scene,
WebGLRenderer,
} from "https://cdn.skypack.dev/three";
function main() {
const scene = new Scene();
const renderer = new WebGLRenderer({
antialias: true,
alpha: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setViewport(0, 0, window.innerWidth, window.innerHeight);
renderer.setClearColor(new Color(0,0,0),0);
}
main();
沒有使用過3D建模軟體的人可能會不太明白Camera
的概念。
在3D建模軟體中,Camera
的用途就是把景物"照"下來。
我們前面有提到,three.js
要渲染畫面的時候要透過renderer
的render
方法,我們除了要告訴renderer
是要渲染哪一個景以外,還得告訴他是要使用那個景裡面的哪一台Camera
,這樣才可以取得那台Camera
照出來的圖像。
這張圖片(來源)稍微有點不正確,其實成像畫面不應該呈現在Near Clip plane上面。
Camera
(相機)有很多種類型,每一種都各有各的使用場景。
在這邊我們使用PerspectiveCamera
這個類所生成的相機實例,所謂的"Perspective"就是"透視法",所謂的"透視法"是一種繪畫的技法,用來把實際的三維空間的座標點,投射到二維平面上。
關於透視法,我去年有寫過一篇3維投影相關的技術文章,可以參考這裡
PerspectiveCamera
這個類必須要傳入4個參數,分別是FOV
,畫面長寬比
,近平面
,遠平面
。
FOV
: 也就是攝影機的水平視角(Field of View),基本上所有的光學成像儀器都會有FOV
的設置,以人眼來講,人眼的FOV大約是120度,超出視角的東西就不會在成像畫面中顯示出來。畫面長寬比
:就是預期成像畫面的長寬比。近平面/遠平面
:其實就是一種範圍限制,攝影機不會把比近平面還要近,或是位置超出遠平面的東西照進去畫面。另外順帶一提,three.js
的PerspectiveCamera
模仿的是現實生活中的35mm
相機,也就是預設具備35mm
的焦距,再換句話說就是攝影機到成像平面(上圖的z-projection平面)的預設距離為35單位長。
初始化過
PerspectiveCamera
的實例之後,記得要add
進去Scene
裡面。
import {
Scene,
WebGLRenderer,
PerspectiveCamera
} from "https://cdn.skypack.dev/three";
function main() {
...
const camera = new PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
scene.add(camera)
}
main();